using System;
using UnityEngine;

namespace GGPhysics
{
	[Serializable]
	public class PhysicsBodyDefinition
	{
		[Range(0f, 10000f)]
		public float dynamicFrictionCoefficient;

		[Range(0f, 1f)]
		public float rollingFrictionCoefficient;

		[Range(0f, 1f)]
		public float restitutionCoefficient;

		public float dynamicFrictionPriority;

		public float coefficientOfRestitutionPriority;

		public float rotationAroundYAxisDragDeceleration = 10f;

		[Range(0f, 1f)]
		public float maxFractionOfOriginallyDirectedSpinLeft = 1f;

		public int radiusFractionAboveCentreOfCollisionPriority;

		public bool shouldRollAlongMotionAfterCollision;

		public bool applyThrow;

		public bool useHeightOffsetInCollision;

		public float heightOffsetRadiusFactor = 0.4f;

		[Header("Velocity Dependant Friction")]
		public bool useVelocityFriction;

		public Vector3 frictionCoefficients;

		public PhysicsBodyDefinition Clone()
		{
			PhysicsBodyDefinition physicsBodyDefinition = new PhysicsBodyDefinition();
			physicsBodyDefinition.dynamicFrictionCoefficient = dynamicFrictionCoefficient;
			physicsBodyDefinition.dynamicFrictionPriority = dynamicFrictionPriority;
			physicsBodyDefinition.rollingFrictionCoefficient = rollingFrictionCoefficient;
			physicsBodyDefinition.restitutionCoefficient = restitutionCoefficient;
			physicsBodyDefinition.coefficientOfRestitutionPriority = coefficientOfRestitutionPriority;
			physicsBodyDefinition.rotationAroundYAxisDragDeceleration = rotationAroundYAxisDragDeceleration;
			physicsBodyDefinition.maxFractionOfOriginallyDirectedSpinLeft = maxFractionOfOriginallyDirectedSpinLeft;
			physicsBodyDefinition.radiusFractionAboveCentreOfCollisionPriority = radiusFractionAboveCentreOfCollisionPriority;
			physicsBodyDefinition.applyThrow = applyThrow;
			physicsBodyDefinition.useHeightOffsetInCollision = useHeightOffsetInCollision;
			physicsBodyDefinition.heightOffsetRadiusFactor = heightOffsetRadiusFactor;
			physicsBodyDefinition.useVelocityFriction = useVelocityFriction;
			physicsBodyDefinition.frictionCoefficients = frictionCoefficients;
			return physicsBodyDefinition;
		}

		public static float Restitution(PhysicsBodyDefinition a, PhysicsBodyDefinition b)
		{
			if (a.coefficientOfRestitutionPriority > b.coefficientOfRestitutionPriority)
			{
				return a.restitutionCoefficient;
			}
			return b.restitutionCoefficient;
		}

		public float FrictionForVelocity(float v)
		{
			if (!useVelocityFriction)
			{
				return dynamicFrictionCoefficient;
			}
			v = Mathf.Abs(v);
			float x = frictionCoefficients.x;
			float y = frictionCoefficients.y;
			float z = frictionCoefficients.z;
			float f = (float)Math.E;
			return x + y * Mathf.Pow(f, (0f - z) * v);
		}

		public static float DynamicFriction(PhysicsBodyDefinition a, PhysicsBodyDefinition b)
		{
			if (a.dynamicFrictionPriority > b.dynamicFrictionPriority)
			{
				return a.dynamicFrictionCoefficient;
			}
			return b.dynamicFrictionCoefficient;
		}

		public static float DynamicFriction(PhysicsBodyDefinition a, PhysicsBodyDefinition b, float v)
		{
			if (a.dynamicFrictionPriority > b.dynamicFrictionPriority)
			{
				return a.FrictionForVelocity(v);
			}
			return b.FrictionForVelocity(v);
		}
	}
}
